package edu.mse.camel.client.whiteboard.gef.ui.editpart;

import java.util.List;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.editparts.AbstractTreeEditPart;
import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
import org.eclipse.swt.graphics.Image;

import edu.mse.camel.client.log.Debug;
import edu.mse.camel.client.whiteboard.gef.ui.WhiteboardPlugin;
import edu.mse.camel.client.whiteboard.gef.whiteboard.WhiteboardDiagram;
import edu.mse.camel.client.whiteboard.gef.whiteboard.WhiteboardPackage;


/**
 * TreeEditPart for a ShapesDiagram instance.
 * This is used in the Outline View of the ShapesEditor.
 * <p>This edit part must implement the PropertyChangeListener interface, 
 * so it can be notified of property changes in the corresponding model element.
 * </p>
 * 
 * @author darpan
 */
public class WhiteboardDiagramTreeEditPart extends AbstractTreeEditPart implements Adapter {
	
	private Notifier target;
	
	/** 
	 * Create a new instance of this edit part using the given model element.
	 * @param model a non-null ShapesDiagram instance
	 */
	WhiteboardDiagramTreeEditPart(WhiteboardDiagram model) {
		super(model);
	}
	
	/**
	 * Upon activation, attach to the model element as a property change listener.
	 */
	@Override
	public void activate() {
		if (!isActive()) {
			hookIntoModel(getCastedModel());
			super.activate();
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.examples.shapes.parts.ShapeTreeEditPart#createEditPolicies()
	 */
	protected void createEditPolicies() {
		// If this editpart is the root content of the viewer, then disallow removal
		if (getParent() instanceof RootEditPart) {
			installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
		}
	}
	
	/**
	 * Upon deactivation, detach from the model element as a property change listener.
	 */
	public void deactivate() {
		if (isActive()) {
			unhookFromModel(getCastedModel());
			super.deactivate();
		}
	}
	
	private void hookIntoModel(EObject model) {
		if(model != null) {
			model.eAdapters().add(this);
		}
	}
	
	private void unhookFromModel(EObject model) {
		if(model != null) {
			model.eAdapters().remove(this);
		}
	}
	
	private WhiteboardDiagram getCastedModel() {
		return (WhiteboardDiagram) getModel();
	}
	
	/**
	 * Convenience method that returns the EditPart corresponding to a given child.
	 * @param child a model element instance
	 * @return the corresponding EditPart or null
	 */
	private EditPart getEditPartForChild(Object child) {
		return (EditPart) getViewer().getEditPartRegistry().get(child);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
	 */
	protected List getModelChildren() {
		return getCastedModel().getShapes(); // a list of shapes
	}
	
	public void notifyChanged(Notification notification) {
		int type = notification.getEventType();
		int featureId = notification.getFeatureID(WhiteboardPackage.class);
		try {
			switch(featureId) {
			case WhiteboardPackage.WHITEBOARD_DIAGRAM__SHAPES:
				switch(type) {
				case Notification.ADD:
					addChild(createChild(notification.getNewValue()), -1);
					break;
				case Notification.REMOVE:
					removeChild(getEditPartForChild(notification.getOldValue()));
					break;
				}
			}
		} catch (Exception e) {
			Debug.log_error(WhiteboardPlugin.PLUGIN_ID, e.getMessage());
			e.printStackTrace();
		}
	}
	
	public Notifier getTarget() {
		return target;
	}
	
	public void setTarget(Notifier newTarget) {
		target = newTarget;
	}
	
	public boolean isAdapterForType(Object type) {
		return getModel() == type;
	}
	
	/**
	 * Override this method to return the
	 * <code>Image</code> for this EditPart's {@link #widget}. This method is called from
	 * {@link #refreshVisuals()}.
	 * @return the Image to be displayed in the TreeItem
	 */
	protected Image getImage() {
		return WhiteboardPlugin.getImageDescriptor("icons/ellipse16.gif").createImage();
	}

	/**
	 * Override this method to return the String to be
	 * used in this EditPart's {@link #widget}. This method is called from {@link
	 * #refreshVisuals()}.
	 * @return the String to be displayed by the TreeItem
	 */
	protected String getText() {
		return "Whiteboard";
	}
	
}
